package br.ufpb.di.knowledgetv.sqtv.modules;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CountDownLatch;

import br.ufpb.di.knowledgetv.sqtv.services.AbstractService;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import br.ufpb.di.knowledgetv.sqtv.utils.Data;

import com.hp.hpl.jena.rdf.model.Resource;

@Component
public class LinkedDataSearchModule implements SQTVModule {

    Logger logger = Logger.getLogger(LinkedDataSearchModule.class);

	@Autowired
	private List<AbstractService> services;
	
	public Data execute(Data data) {

        ConcurrentLinkedQueue<Resource> results = new ConcurrentLinkedQueue<Resource>();
        CountDownLatch latch = new CountDownLatch(this.services.size());
		for (AbstractService service : this.services) {
            Thread t = new Thread(new SearchThread(service, data, results, latch));
            t.start();
		}

        try {
            latch.await();
        } catch (InterruptedException e) {
            logger.error(e.getMessage());
        }
        ArrayList<Resource> resultsAsList = new ArrayList<Resource>();
        resultsAsList.addAll(results);
        data.addData("ld_results", resultsAsList);
        return data;
	}

    private class SearchThread implements Runnable {

        private AbstractService service;
        private Data data;
        private ConcurrentLinkedQueue<Resource> resources;
        private CountDownLatch latch;

        private SearchThread(AbstractService service, Data data, ConcurrentLinkedQueue<Resource> resources, CountDownLatch latch) {
            this.service = service;
            this.data = data;
            this.resources = resources;
            this.latch = latch;
        }

        @Override
        public void run() {
            try {
                List<Resource> r = service.searchByKeyword((String) data.getData("keywords"));
                if(r != null)
                    resources.addAll(r);
            } catch (Exception e) {
                logger.error(e.getMessage());
            } finally {
                this.latch.countDown();
            }
        }
    }

}